package com.hursing.tractor.controller;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import android.os.Handler;
import android.os.Message;

import com.hursing.tractor.baseview.UIView;
import com.hursing.tractor.baseview.UIWindow;
import com.hursing.tractor.model.Player;
import com.hursing.tractor.model.Card;
import com.hursing.tractor.model.CardPattern;
import com.hursing.tractor.model.GameData;
import com.hursing.tractor.model.Strategy;

final class PlayStage extends Stage implements PlayController {

	private static final int MESSAGE_PLAY_CARD = 0;
	private static final int MESSAGE_NETX_ROUND = 1;
	private static final int MESSAGE_FINISH_GAME = 2;
	
	private static final int INTERVAL_PLAY_CARD = 1;
	private static final int INTERVAL_NEXT_ROUND = 1000;
	private static final int INTERVAL_FINISH_GAME = 10;
		
	private int mFirstPosition;
	private int mCurrentLargestPosition;
	private int mStep;
	private CardPattern mLargestCardPattern;
	
	private Handler mPlayHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MESSAGE_PLAY_CARD:
				notifyPlayCard();
				break;
			case MESSAGE_NETX_ROUND:
				nextRound();
				break;
			case MESSAGE_FINISH_GAME:
				finishGame();
				break;
			default:
				break;
			}
		}
	};

	@Override
	public void start() {
		mCurrentLargestPosition = GameData.instance().housePosition();
		UIView.sViews[UIView.VIEW_VIEW_KITTY_BUTTON].enabled(
				GameData.instance().housePosition() == GameData.instance().handPosition());
		UIView.sViews[UIView.VIEW_PLAY_PANEL].visible(true);
		nextRound();
	}
	
	/**
	 * 
	 * @return 是否结局
	 */
	private boolean finishRound() {
		// 结局
		boolean hasFinished = GameData.instance().player(mFirstPosition).handyCardCount() == 0;
		for (int i = 0; i < Player.PLAYER_COUNT; i++) {
			GameData.instance().lastRoundCards().get(i).clear();
			GameData.instance().lastRoundCards().get(i).addAll(GameData.instance().playedCards().get(i));
		}
		// 算分
		if (GameData.instance().isGettingMark(mCurrentLargestPosition)) {
			GameData.instance().scoreplus(currentPlayedMarks());
			// 底牌分
			if (hasFinished) {
				int kittyMark = calculateMark(GameData.instance().kittyCards());
				int times = 2;
				if (mLargestCardPattern.tractors().size() != 0) {
					times = (int) Math.pow(2, mLargestCardPattern.tractorCards(0).size());
				} else if (mLargestCardPattern.pairs().size() != 0) {
					times = 4;
				}
				GameData.instance().scoreplus(kittyMark * times);
			}
		}
		return hasFinished;
	}
	
	private void finishGame() {
		Strategy.instance().calculateResult();
		nextStage();
	}
	
	private void nextPlayStep() {
		if (mStep == 4) {
			if (finishRound()) {
				UIView.sViews[UIView.VIEW_KITTY_CARD].visible(true);
				mPlayHandler.sendEmptyMessageDelayed(MESSAGE_FINISH_GAME, INTERVAL_FINISH_GAME);
			} else {
				mPlayHandler.sendEmptyMessageDelayed(MESSAGE_NETX_ROUND, INTERVAL_NEXT_ROUND);
			}
		} else {
			mPlayHandler.sendEmptyMessageDelayed(MESSAGE_PLAY_CARD, INTERVAL_PLAY_CARD);
		}
	}
	
	private void nextRound() {
		mFirstPosition = mCurrentLargestPosition;
		mStep = 0;
		GameData.instance().clearPlayedCards();
		nextPlayStep();
	}
	
	@Override
	public void collectPlayedCard(Player player, LinkedList<Card> cards) {
		if (mStep == 0) {
			CardPattern cp = new CardPattern(cards);
			if (cp.isThrow()) {
				LinkedList<Card> smallest = null;
				for (int i = 1; i < Player.PLAYER_COUNT; i++) {
					int position = (mFirstPosition + i) % Player.PLAYER_COUNT;
					LinkedList<Card> reject = GameData.instance().player(position).canThrow(cp);
					if (reject.size() == 0) {
						continue;
					} else {
						if (smallest == null || smallest.size() > reject.size()) {
							smallest = reject;
						}
						if (reject.size() == 1) {
							break;
						}
					}
				}
				if (smallest != null) {
					cards.clear();
					cards.addAll(smallest);
					UIWindow.instance().tipRejectThrow();
				}
			}
		}
		GameData.instance().playedCards(cards, player.position());
		checkLargest(cards);
		mStep++;
		nextPlayStep();
	}
	
	private void notifyPlayCard() {
		int position = (mFirstPosition + mStep) % Player.PLAYER_COUNT;
		GameData.instance().player(position).playCard(this);
	}
	
	public int getCurrentStep() {
		return mStep;
	}
	
	@Override
	public ArrayList<LinkedList<Card>> getPlayedCardsInPlayingOrder() {
		ArrayList<LinkedList<Card>> cards = new ArrayList<LinkedList<Card>>(Player.PLAYER_COUNT);
		for (int i = 0; i < mStep; i++) {
			int position = (mFirstPosition + i) % Player.PLAYER_COUNT;
			cards.add(GameData.instance().playedCards().get(position));
		}
		return cards;
	}
	
	private void checkLargest(LinkedList<Card> cards) {
		if (mStep == 0) {
			mLargestCardPattern = new CardPattern(cards);
		} else {
			CardPattern current = new CardPattern(cards);
			if (current.isLargerThanCurrentLargest(mLargestCardPattern)) {
				mLargestCardPattern = current;
				mCurrentLargestPosition = (mFirstPosition + mStep) % Player.PLAYER_COUNT;
			}
		}
	}

	@Override
	void pause() {		
	}

	@Override
	void recover() {
		
	}

	@Override
	public CardPattern largestCardPattern() {
		return mLargestCardPattern;
	}
	
	private int calculateMark(List<Card> cards) {
		int mark = 0;
		ListIterator<Card> itor = cards.listIterator();
		while (itor.hasNext()) {
			mark += itor.next().mark();
		}
		return mark;
	}

	@Override
	public int currentPlayedMarks() {
		int mark = 0;
		ListIterator<LinkedList<Card>> itor = GameData.instance().playedCards().listIterator();
		while (itor.hasNext()) {
			mark += calculateMark(itor.next());
		}
		return mark;
	}

	@Override
	public int currentOrder() {
		return mStep;
	}

}
